package com.ebt.m.utils;

import android.content.ContentValues;
import android.database.Cursor;
import android.util.Log;

import com.ebt.m.customer.util.CompareHelper;
import com.ebt.m.data.DataAnnotationExcept;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.UUID;

/**
 * 操作sqlite数据的工具类
 */
public class DataUtils {

	public DataUtils() {

	}

	/**
	 * 根据对象实体获得contentvalues
	 *
	 * @param obj
	 * @return
	 */
	public ContentValues getContentValues(Object obj) {
		if (null == obj) {
			return null;
		}
		ContentValues values = new ContentValues();
		try {
			Class<?> clazz = obj.getClass();
			Field[] fs = clazz.getDeclaredFields();
			for (Field f : fs) {
				String name = f.getName();
				boolean except = f.isAnnotationPresent(DataAnnotationExcept.class);
				if (except) {
					continue;
				}
				if ("serialVersionUID".equalsIgnoreCase(name)) {
					continue;
				}
				Method get = DataUtils.getGetMethod(clazz, f);// 获取get
				Object o = get.invoke(obj);
				Class<?> type = f.getType();
				if (type == String.class) {
					values.put(name, (String) o);
				} else if (type == int.class || type == Integer.class) {
					values.put(name, (Integer) o);
				} else if (type == float.class || type == Float.class) {
					values.put(name, (Float) o);
				} else if (type == double.class || type == Double.class) {
					values.put(name, (Double) o);
				} else if (type == long.class || type == Long.class) {
					values.put(name, (Long) o);
				} else if (type == Date.class) {
					values.put(name, DateUtils.dateTime2String((Date) o));
				} else if (type.isArray()) {
					values.put(name, (byte[]) o);
				} else {
					values.put(name, o == null ? "" : o.toString());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return values;
	}

	/**
	 * 将数据库记录转换为对象
	 *
	 * @param cursor
	 * @param entity
	 * @return
	 */
	public <T> T getEntity(Cursor cursor, T entity) {
		// if (!cursor.moveToFirst()) {
		// return entity;
		// }
		String field = "";
		try {
			Class<?> entity_class = entity.getClass();
			Field[] fs = entity_class.getDeclaredFields();
			for (Field f : fs) {
				field = f.getName();
				Class<?> type = f.getType();
				int index = cursor.getColumnIndex(field);
				if (index < 0) {
					continue;
				}
				Method set = getSetMethod(entity_class, f);
				if (set != null) {
					if (type == String.class) {
						String value = cursor.getString(index);
						set.invoke(entity, value);
					} else if (type == int.class || type == Integer.class) {
						set.invoke(entity, cursor.isNull(index) ? null : cursor.getInt(index));
						// String value = cursor.getString(index);
						// set.invoke(entity,value==null?null:Integer.parseInt(value));
					} else if (type == float.class || type == Float.class) {
						// float value = cursor.getFloat(index);
						// set.invoke(entity, value);
						// set.invoke(entity, cursor.isNull(index) ? (Float)
						// null
						// : cursor.getFloat(index));
						// String value = cursor.getString(index);
						// set.invoke(entity,value==null?null:Float.parseFloat(value));
						set.invoke(entity, cursor.isNull(index) ? null : cursor.getFloat(index));
					} else if (type == double.class || type == Double.class) {
						// double value = cursor.getDouble(index);
						// set.invoke(entity, value);
						// String value = cursor.getString(index);
						// set.invoke(entity,value==null?null:Double.parseDouble(value));
						set.invoke(entity, cursor.isNull(index) ? null : cursor.getDouble(index));
					} else if (type == long.class || type == Long.class) {
						// long value = cursor.getLong(index);
						// set.invoke(entity, value);
						// String value = cursor.getString(index);
						// set.invoke(entity,value==null?null:Long.parseLong(value));
						set.invoke(entity, cursor.isNull(index) ? null : cursor.getLong(index));
					} else if (type == Date.class) {
						set.invoke(entity, cursor.isNull(index) ? (Date) null : DateUtils.stringToDateTime(cursor.getString(index)));
					} else if (type.isArray()) {
						// blob类型数据
						byte[] value = cursor.getBlob(index);
						set.invoke(entity, value);
					}
				}
			}
			return entity;
		} catch (Exception e) {
			System.out.println("报异常的域：" + field);
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		}
	}

    /**
     * 将数据库记录转换为对象
     *  //TODO 待优化，可将field、type等进行hashmap缓存
     * @param cursor
     * @param entity
     * @return
     */
    public <T> T getEntityOverride(Cursor cursor, T entity) {
        Field field = null;
        try {
            Class<?> entity_class = entity.getClass();
            Field[] fs = entity_class.getDeclaredFields();
            if(fs == null) return entity;
            ArrayList<String> tempFields = new ArrayList(fs.length);
            for(Field temp : fs){
                tempFields.add(temp.getName());
            }
            //// TODO: 2016/7/5
            Collections.sort(tempFields, CompareHelper.COMPARATOR_STRING_ASC);

            String[] arrayFields = new String[tempFields.size()];
            arrayFields = tempFields.toArray(arrayFields);

            int columnCount = cursor.getColumnCount();
            for(int index = 0; index < columnCount; index++){
                String columnName = cursor.getColumnName(index);
//                if(Arrays.binarySearch())
                int ret = Arrays.binarySearch(arrayFields, columnName, CompareHelper.COMPARATOR_STRING_ASC);
                if(ret < 0) continue;

                Field f = entity_class.getDeclaredField(columnName);
                field = f;
                f.setAccessible(true);
                Class<?> type = f.getType();
                if (type == String.class) {
                    String value = cursor.getString(index);
                    f.set(entity, value);
                } else if (type == int.class || type == Integer.class) {
                    f.set(entity, cursor.isNull(index) ? null : cursor.getInt(index));
                } else if (type == float.class || type == Float.class) {
                    f.set(entity, cursor.isNull(index) ? null : cursor.getFloat(index));
                } else if (type == double.class || type == Double.class) {
                    f.set(entity, cursor.isNull(index) ? null : cursor.getDouble(index));
                } else if (type == long.class || type == Long.class) {
                    f.set(entity, cursor.isNull(index) ? null : cursor.getLong(index));
                } else if (type == Date.class) {
                    boolean isnull = cursor.isNull(index);
                    if(isnull){
                        f.set(entity, null);
                    }else{
//                        cursor.getType()//TODO
                        String cursorString = cursor.getString(index);
                        f.set(entity, DateUtils.stringToDateTime(cursor.getString(index)));
                    }
//                    f.set(entity, cursor.isNull(index) ? null : DateUtils.stringToDateTime(cursor.getString(index)));
                } else if (type.isArray()) {
                    byte[] value = cursor.getBlob(index);
                    f.set(entity, value);
                }
            }
            return entity;
        } catch (Exception e) {
            System.out.println("报异常的域：" + field.getName());
            e.printStackTrace();
            throw new RuntimeException(e.getMessage(), e);
        }
    }

	/**
	 * 反射获得get方法对象
	 *
	 * @param entity_class
	 * @param f
	 * @return
	 */
	public static Method getGetMethod(Class<?> entity_class, Field f) {
		String fn = f.getName();
		String mn = "get" + fn.substring(0, 1).toUpperCase() + fn.substring(1);
		try {
			return entity_class.getDeclaredMethod(mn);
		} catch (NoSuchMethodException e) {
			Log.w(EbtUtils.getTag(DataUtils.class), "Method: " + mn + " not found.");

			return null;
		}
	}

	/**
	 * 反射获得set方法对象
	 *
	 * @param entity_class
	 * @param f
	 * @return
	 */
	public static Method getSetMethod(Class<?> entity_class, Field f) {
		String fn = f.getName();
		String mn = "set" + fn.substring(0, 1).toUpperCase() + fn.substring(1);
		try {
			return entity_class.getDeclaredMethod(mn, f.getType());
		} catch (NoSuchMethodException e) {
			Log.w(EbtUtils.getTag(DataUtils.class), "Method: " + mn + " not found.");
			return null;
		}
	}

	/**
	 * 使用javaAPI生成UUID RFC4122
	 *
	 * @return
	 */
	public static String getRandomUUID() {
		return UUID.randomUUID().toString();
	}
}
